package org.infodavid.common.persistence;

import java.util.Collection;
import java.util.List;

import javax.persistence.PersistenceException;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.infodavid.common.model.IGenericProperty;
import org.infodavid.common.model.IUser;
import org.infodavid.common.model.IUserGroup;
import org.infodavid.common.model.criteria.IGenericPropertyCriteria;
import org.infodavid.common.model.criteria.ISearchCriteria;
import org.infodavid.common.persistence.impl.AbstractDataService;
import org.infodavid.common.reflect.InstantiationHelper;
import org.joda.time.DateTime;

/**
 * The Class UserDataService.
 */
public abstract class UserDataService extends AbstractDataService<IUser,Long> {

  /** The Constant log. */
  private static final Log LOGGER = LogFactory.getLog(UserDataService.class);

  /** The singleton. */
  private static final UserDataService SINGLETON;

  static {
    try {
      SINGLETON = InstantiationHelper.getInstance().newInstance(UserDataService.class);
    }
    catch (final Exception e) {
      LOGGER.fatal("Can not instantiate the " + UserDataService.class.getName(), e);

      throw new Error(e);
    }
  }

  /**
   * returns the singleton.
   * @return the singleton
   */
  public static UserDataService getInstance() {
    return SINGLETON;
  }

  /**
   * Instantiates a new service.
   */
  protected UserDataService() {
    super();
  }

  /**
   * Find by email.
   * @param session the session
   * @param value the value
   * @return the user
   * @throws PersistenceException the persistence exception
   */
  public abstract IUser findByEmail(PersistenceSession session, String value)
      throws PersistenceException;

  /**
   * Find the users by their group.
   * @param session the session
   * @param key the key of the group
   * @param results the list of users
   * @param criteria the criteria
   * @return the number of results
   * @throws PersistenceException the persistence exception
   */
  public abstract long findByGroup(PersistenceSession session, Long key, List<IUser> results,
      ISearchCriteria criteria) throws PersistenceException;

  /**
   * Find by name.
   * @param session the session
   * @param value the value
   * @return the user
   * @throws PersistenceException the persistence exception
   */
  public abstract IUser findByName(PersistenceSession session, String value)
      throws PersistenceException;

  /**
   * Find the users by the type of the groups they belong.
   * @param session the session
   * @param role the role of the groups
   * @param results the results
   * @param criteria the criteria
   * @return the number of results
   * @throws PersistenceException the persistence exception
   */
  public abstract long findByRole(PersistenceSession session, IUserGroup.EUserRole role,
      List<IUser> results, ISearchCriteria criteria) throws PersistenceException;

  /**
   * Find the properties using the scope.
   * @param context the context
   * @param userKey the user key
   * @param criteria the criteria
   * @param results the resulting properties
   */
  public abstract void findProperties(PersistenceSession session,
      Collection<IGenericProperty> results, long userKey, IGenericPropertyCriteria criteria)
      throws PersistenceException;

  /**
   * Find roles according to the groups.
   * @param session the session
   * @param key the key
   * @return the results
   * @throws PersistenceException the persistence exception
   */
  public abstract List<IUserGroup.EUserRole> findRoles(PersistenceSession session, Long key)
      throws PersistenceException;

  /**
   * Sets the properties.
   * @param context the context
   * @param userKey the user key
   * @param properties the properties to update
   * @return the modification associated to the application settings entity
   */
  public abstract DateTime updateProperties(PersistenceSession session, long userKey,
      Collection<IGenericProperty> properties) throws PersistenceException;
}
